package example.grid.core;

import com.alicloud.openservices.tablestore.*;
import com.alicloud.openservices.tablestore.model.GetRowResponse;
import com.alicloud.openservices.tablestore.model.Row;
import com.alicloud.openservices.tablestore.model.search.CreateSearchIndexRequest;
import com.alicloud.openservices.tablestore.model.search.IndexSchema;
import com.alicloud.openservices.tablestore.model.search.SearchResponse;
import com.alicloud.openservices.tablestore.model.search.query.Query;
import com.alicloud.openservices.tablestore.writer.WriterConfig;
import com.aliyun.tablestore.grid.*;
import com.aliyun.tablestore.grid.core.RequestBuilder;
import com.aliyun.tablestore.grid.core.RowParser;
import com.aliyun.tablestore.grid.core.TableStoreDataFetcher;
import com.aliyun.tablestore.grid.core.TableStoreDataWriter;
import com.aliyun.tablestore.grid.model.GridDataSetMeta;
import com.aliyun.tablestore.grid.model.QueryGridDataSetResult;
import com.aliyun.tablestore.grid.model.QueryParams;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class MyTableStoreGrid implements GridStore {
    private TableStoreGridConfig config;
    public AsyncClientInterface asyncClient;
    private ExecutorService writerExecutor;
    private TableStoreWriter writer;
    private static Logger logger = LogManager.getLogger(MyTableStoreGrid.class);

    public MyTableStoreGrid(TableStoreGridConfig config) {
        this.config = config;
        this.asyncClient = new AsyncClient(config.getTableStoreEndpoint(), config.getAccessId(), config.getAccessKey(), config.getTableStoreInstance());
    }

    public void createStore() throws Exception {
        try {
            this.asyncClient.createTable(MyRequestBuilder.buildCreateMetaTableRequest(this.config.getMetaTableName()), (TableStoreCallback)null).get();
        } catch (TableStoreException var3) {
            if (!var3.getErrorCode().equals("OTSObjectAlreadyExist")) {
                throw var3;
            }
            logger.info(var3.getErrorCode());
        }

        try {
            this.asyncClient.createTable(MyRequestBuilder.buildCreateDataTableRequest(this.config.getDataTableName()), (TableStoreCallback)null).get();
        } catch (TableStoreException var2) {
            if (!var2.getErrorCode().equals("OTSObjectAlreadyExist")) {
                throw var2;
            }
        }

    }

    public void putDataSetMeta(GridDataSetMeta meta) throws Exception {
        this.asyncClient.putRow(RequestBuilder.buildPutMetaRequest(this.config.getMetaTableName(), meta), (TableStoreCallback)null).get();
    }

    public void updateDataSetMeta(GridDataSetMeta meta) throws Exception {
        this.asyncClient.updateRow(RequestBuilder.buildUpdateMetaRequest(this.config.getMetaTableName(), meta), (TableStoreCallback)null).get();
    }

    public GridDataSetMeta getDataSetMeta(String gridDataSetId) throws Exception {
        GetRowResponse getRowResponse = (GetRowResponse)this.asyncClient.getRow(RequestBuilder.buildGetMetaRequest(this.config.getMetaTableName(), gridDataSetId), (TableStoreCallback)null).get();
        return getRowResponse.getRow() == null ? null : RowParser.parseMetaFromRow(getRowResponse.getRow());
    }

    public void createMetaIndex(String indexName, IndexSchema indexSchema) throws Exception {
        CreateSearchIndexRequest request = new CreateSearchIndexRequest();
        request.setTableName(this.config.getMetaTableName());
        request.setIndexName(indexName);
        request.setIndexSchema(indexSchema);
        this.asyncClient.createSearchIndex(request, (TableStoreCallback)null).get();
    }

    public QueryGridDataSetResult queryDataSets(String indexName, Query query, QueryParams queryParams) throws Exception {
        SearchResponse searchResponse = (SearchResponse)this.asyncClient.search(RequestBuilder.buildSearchRequest(this.config.getMetaTableName(), indexName, query, queryParams), (TableStoreCallback)null).get();
        List<GridDataSetMeta> metaList = new ArrayList();
        Iterator var6 = searchResponse.getRows().iterator();

        while(var6.hasNext()) {
            Row row = (Row)var6.next();
            metaList.add(RowParser.parseMetaFromRow(row));
        }

        QueryGridDataSetResult result = new QueryGridDataSetResult();
        result.setGridDataSetMetas(metaList);
        result.setAllSuccess(searchResponse.isAllSuccess());
        result.setNextToken(searchResponse.getNextToken());
        result.setTotalCount(searchResponse.getTotalCount());
        return result;
    }

    public GridDataWriter getDataWriter(GridDataSetMeta meta) {
        if (this.writer == null) {
            synchronized(this) {
                if (this.writer == null) {
                    this.writerExecutor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
                    this.writer = new DefaultTableStoreWriter(this.asyncClient, this.config.getDataTableName(), new WriterConfig(), (TableStoreCallback)null, this.writerExecutor);
                }
            }
        }

        return new MyTableStoreDataWriter(this.writer, this.config.getDataTableName(), meta);
    }

    public GridDataFetcher getDataFetcher(GridDataSetMeta meta) {
        return new TableStoreDataFetcher(this.asyncClient, this.config.getDataTableName(), meta, this.config.getDataSizeLimitForFetch());
    }

    public synchronized void close() {
        if (this.writer != null) {
            this.writer.close();
            this.writerExecutor.shutdown();
        }

        this.asyncClient.shutdown();
    }
}
